package com.jishuo.nontax.bfc.service;


import com.github.pagehelper.PageHelper;
import com.jishuo.base.bean.BaseResult;
import com.jishuo.base.bean.ErrorCodeEnum;
import com.jishuo.base.bean.Pagination;
import com.jishuo.base.bean.vo.UserVO;
import com.jishuo.base.config.NonTaxConfig;
import com.jishuo.base.service.SequenceService;
import com.jishuo.base.util.CommonUtil;
import com.jishuo.base.util.ExportSXSSFUtil;
import com.jishuo.base.util.GTimeUtil;
import com.jishuo.base.util.StringUtil;
import com.jishuo.nontax.bean.bank.ChargeBillIsActive;
import com.jishuo.nontax.bean.bank.OnlineOrder;
import com.jishuo.nontax.bean.message.*;
import com.jishuo.nontax.bean.vo.BankStationVO;
import com.jishuo.nontax.bean.vo.ChargeBillDetailVO;
import com.jishuo.nontax.bean.vo.ChargeBillVO;
import com.jishuo.nontax.bean.vo.WaitaffirmVO;
import com.jishuo.nontax.bfc.dao.BankMapper;
import com.jishuo.nontax.bfc.dao.BaseDataMapper;
import com.jishuo.nontax.bfc.dao.ChargeBillMapper;
import com.jishuo.nontax.bfc.dao.WaitaffirmMapper;
import com.jishuo.nontax.bfc.pzk.PzkService;
import com.jishuo.nontax.bfc.tlq.MessageService;
import com.jishuo.nontax.util.BillStateUtil;
import org.apache.poi.xssf.streaming.SXSSFWorkbook;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * 一般缴款书，单据中keyword固定“82”，billtypeid固定“1”
 * @author hlp
 * @date 2023/2/16 08:59
 */
@Service
public class ChargeBillService {

    private static Logger logger = LoggerFactory.getLogger(ChargeBillService.class);

    @Resource
    private ChargeBillMapper chargeBillMapper;
    @Resource
    private WaitaffirmMapper waitaffirmMapper;
    @Resource
    private BaseDataMapper baseDataMapper;
    @Resource
    private SequenceService sequenceService;
    @Resource
    private BankMapper bankMapper;
    @Resource
    private MessageService messageService;
    @Resource
    private NonTaxConfig nonTaxConfig;
    @Resource
    private OnlineOrderService onlineOrderService;
    @Resource
    private PzkService pzkService;

    private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");


    /**
     * @author hlp
     * @date 2023/3/6 11:09
     * @Description: 新增缴款书细单，web页面
     */
    public BaseResult saveDetail(ChargeBillDetailVO detailid) {
        List<ChargeBillDetailVO> chargeBillDetailVOS = new ArrayList<>();
        chargeBillDetailVOS.add(detailid);
        int i = chargeBillMapper.saveChargeBillManualDetail(chargeBillDetailVOS);
        if (i > 0) {
            return new BaseResult();
        }
        return new BaseResult(ErrorCodeEnum.DB_ERR);
    }

    /**
     * @author hlp
     * @date 2023/3/6 14:22
     * @Description: 修改缴款书，web页面
     */
    public BaseResult updateChargeBill(ChargeBillVO chargeBillVO) {
        ArrayList<ChargeBillDetailVO> chargeBillDetails = chargeBillMapper.chargeBillDetailList(chargeBillVO.getBillid());
        BigDecimal sumfund = new BigDecimal(0);
        for (ChargeBillDetailVO chargeBillDetail : chargeBillDetails) {
            BigDecimal originfund = chargeBillDetail.getOriginfund();
            if (sumfund != new BigDecimal(0)) {
                sumfund = originfund.add(sumfund);
            }
        }
        chargeBillVO.setOriginfund(sumfund);
        int i = chargeBillMapper.updateChargeBillNum(chargeBillVO);
        if (i > 0) {
            return new BaseResult();
        }
        return new BaseResult(ErrorCodeEnum.DB_ERR);
    }

    /**
     * @author hlp
     * @date 2023/3/6 11:08
     * @Description: 删除缴款书详细单据，web页面
     */
    public BaseResult deleteChargebilldetailId(long detailid) {
        int i = chargeBillMapper.deleteChargebilldetailId(detailid);
        if (i > 0) {
            return new BaseResult();
        }
        return new BaseResult(ErrorCodeEnum.DB_ERR);
    }

    /**
     * 获得缴款书列表，web页面
     *
     * @return
     */
    public List<ChargeBillVO> listChargeBill(ChargeBillVO chargeBillVO, Pagination pagination) {
        // 当单页条数大于零时，启用分页
        if (pagination.getRows() > 0) PageHelper.startPage(pagination.getPage(), pagination.getRows());
        List<ChargeBillVO> list = this.chargeBillMapper.selectChargeBillPage(chargeBillVO);
        return list;
    }

    /**
     * @author hlp
     * @date 2023/3/24 11:14
     * @Description: 收款，view页面
     */
    public BaseResult chargebillpay(ChargeBillVO chargeBillVO) {
        try {
            //获取银行返回数据
            String paybankdt = sdf.format(new Date());
            chargeBillVO.setPaybankdt(paybankdt); // 付款时间
            chargeBillVO.setIncomeway(0); // 是否待查确认
            BaseResult baseResult = setChargeBillDeposit(chargeBillVO, "");
            return baseResult;
        } catch (Exception e) {
            logger.info("提交缴费异常。", e);
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), "缴费异常");
        }
    }

    /**
     * @author hlp
     * @date 2023/2/15 14:12
     * @Description: 获取缴款书单据，从财政查询
     */
    public BaseResult getChargeBill(String billNum) {
        BaseResult ret = this.getChargeBillVO(billNum);
        if (ret.isSuccess()) {
            try {
                //xml解析器
                Serializer serializer = new Persister();
                //xml转换器
                StringWriter sw = new StringWriter();
                ChargeBillVO chargeBillVO = (ChargeBillVO)ret.getData();
                serializer.write(chargeBillVO.gainChargeBill(), sw);
                return new BaseResult(sw.toString());
            } catch (Exception e) {
                logger.info("处理获取缴款书失败：" + e.toString());
                return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
            }
        }
        return ret;
    }

    /**
     * 财政查询票据
     * @param billNum 票号
     * @return 返回对象
     */
    public BaseResult getChargeBillVO(String billNum) {
        try {
            BaseResult result = new BaseResult();
            //获取缴款书对象
            ChargeBillVO chargeBillVO = chargeBillMapper.findChargeBill(billNum);
            if (chargeBillVO != null) chargeBillVO.setDetailVOS(chargeBillMapper.chargeBillDetailList(chargeBillVO.getBillid()));

            // 已缴费的直接返回
            if (chargeBillVO != null && (chargeBillVO.getBillstate() == 3 || chargeBillVO.getIsbankaffirm() ==1)) {
                chargeBillVO.setBillstate(3);
                result.setData(chargeBillVO);
                result.setMsgExt(BillStateUtil.getBillState(BillStateUtil.BillType_ChargeBill, chargeBillVO.getBillstate()));
                return result;
            }

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            if (chargeBillVO != null) {
                chargeBillVO.setBilltypeid(1);
                chargeBillVO.setKeyword(82);
                chargeBillVO.setMessageid(messageid);
                chargeBillMapper.updateChargeBill(chargeBillVO);
            } else {
                chargeBillVO = new ChargeBillVO();
                chargeBillVO.setBillnum(billNum);
                chargeBillVO.setBilltypeid(1);
                chargeBillVO.setKeyword(82);
                chargeBillVO.setMessageid(messageid);
                chargeBillVO.setIssend(0);
                chargeBillVO.setBillid(sequenceService.getNextSeq("FSCHARGEBILLDETAILSEQ"));
                chargeBillMapper.saveChargeBill(chargeBillVO);
            }

            boolean suc = messageService.sendAndRecvMessage("GETCHARGEBILL", messageid, chargeBillVO.gainGetChargeBill(), "2.0");
            if (suc) {
                chargeBillVO = chargeBillMapper.findChargeBill(billNum);
                chargeBillVO.setDetailVOS(chargeBillMapper.chargeBillDetailList(chargeBillVO.getBillid()));
                result.setData(chargeBillVO);
                result.setMsgExt(BillStateUtil.getBillState(BillStateUtil.BillType_ChargeBill, chargeBillVO.getBillstate()));
                return result;
            }
            return new BaseResult(ErrorCodeEnum.BILL_GET_TIMEOUT);
        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e.toString());
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }

    /**
     * @return 一般缴款书电子票缴费
     * billnum		票号
     * eticketnum	电子票号
     * payer			付款人
     * filldate		票据日期
     * accountcode	非税账户
     * iswaitaffirm	是否待查确认
     * originfund	金额
     * paybankdt		交易时间
     * bankaffirm	交易流水号
     * bankstation	网点
     * paywaycode	付款方式
     * @return
     * @author hlp
     * 一般缴款书电子票缴费
     */
    public BaseResult setChargeBillDeposit(ChargeBillVO chargeBillVo, String paychnl) {
        // 参数检查
        String retMsg = "";
        if (chargeBillVo.getBillnum() == null || "".equals(chargeBillVo.getBillnum())) {
            retMsg += "票号未填写；";
        } else if (chargeBillVo.getIncomeway() < 0 || chargeBillVo.getIncomeway() > 1) {
            retMsg += "待查确认标志错误；";
        } else if (chargeBillVo.getPaybankdt() == null || "".equals(chargeBillVo.getPaybankdt())) {
            retMsg += "缴费时间未填写；";
        } else if (chargeBillVo.getBankaffirm() == null || "".equals(chargeBillVo.getBankaffirm())) {
            retMsg += "交易流水号未填写；";
        } else if (chargeBillVo.getBankstation() == null || "".equals(chargeBillVo.getBankstation())) {
            retMsg += "办理网点未填写；";
        }
        if (chargeBillVo.getPaywaycode().length() == 1) {
            chargeBillVo.setPaywaycode("0" + chargeBillVo.getPaywaycode());
        }
        int paywayid = chargeBillMapper.findPayWay(chargeBillVo.getPaywaycode());
        if (paywayid == 0) {
            retMsg += "付款方式未填写；";
        }
        if (!"".equals(retMsg)) {
            logger.info("缴费参数错误。" + retMsg);
            return new BaseResult("3000", retMsg);
        }

        ChargeBillVO chaBillVO = chargeBillMapper.findChargeBill(chargeBillVo.getBillnum());
        if (chaBillVO == null || chaBillVO.getIshand() == 1) {
            logger.info("电子缴款号不存在（票号：" + chargeBillVo.getBillnum() + "）");
            return new BaseResult(ErrorCodeEnum.BILL_NOT_FOUND);
        }
        // 判断是否已缴费
        if (chaBillVO.getIsbankaffirm() == 1) {
            // 日期一致的允许二次提交
            if (!chargeBillVo.getPaybankdt().substring(0, 10).equals(chaBillVO.getPaybankdt().substring(0, 10)))
                return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        } else if (chaBillVO.getBillstate() == 3) {
            return new BaseResult(ErrorCodeEnum.BILL_PAYED);
        }

        try {
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            chaBillVO.setBankaffirm(chargeBillVo.getBankaffirm());
            chaBillVO.setPaybankdt(chargeBillVo.getPaybankdt());
            chaBillVO.setBankstation(chargeBillVo.getBankstation());
            chaBillVO.setHxbankaffirm(chargeBillVo.getBankaffirm());
            chaBillVO.setSendtime(sdf.format(new Date()));
            chaBillVO.setIsbankaffirm(1);
            chaBillVO.setIncomeway(chargeBillVo.getIncomeway()); // 是否待查确认
            chaBillVO.setPayway(paywayid);

            if (chargeBillMapper.updateChargeBillNumPay(chaBillVO) < 1) {
                return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新一般缴款书机打票失败（" + chaBillVO.getBillnum() + "）");
            }
            //如果待查，将待查状态改为已用状态
            if (chaBillVO.getIncomeway() == 1) {
                WaitaffirmVO waitaffirmVo = new WaitaffirmVO();
                waitaffirmVo.setBankaffirm(chaBillVO.getBankaffirm());
                waitaffirmVo.setBankid(chaBillVO.getBankid());
                waitaffirmVo.setBillstate(3);
                waitaffirmVo.setPaybankdt(chaBillVO.getPaybankdt().substring(0, 10));
                waitaffirmMapper.updateBankAffirm(waitaffirmVo);
            }

            OnlineOrder oo = new OnlineOrder();
            oo.setBillnum(chaBillVO.getBillnum());
            oo.setAmt(chaBillVO.getOriginfund().toPlainString());
            oo.setBankaffirm(chaBillVO.getBankaffirm());
            oo.setBilltype(4);
            oo.setPaybankdt(chaBillVO.getPaybankdt());
            oo.setPaychnl(paychnl);
            oo.setPayee(chaBillVO.getPayee());
            oo.setPayeeaccount(chaBillVO.getPayeeaccount());
            oo.setPayer(chaBillVO.getPayer());
            oo.setPayeraccount(chargeBillVo.getPayeraccount());
            oo.setPaytype(1);
            onlineOrderService.saveOnlineOrder(oo);

            //获取缴款书对象
            SetChargeBillDeposit setChargebill = chaBillVO.gainSetChargeBillDeposit();
            //发送到财政
            boolean success = messageService.sendMessage("SETCHARGEBILLDEPOSIT", messageid, setChargebill, "2.0");
            // 写凭证
            pzkService.savePzmsg("SETCHARGEBILLPZK", chaBillVO);

            return new BaseResult();
        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e.toString(), e);
            return new BaseResult("3100", "缴费异常");
        }
    }

    /**
     * billNum  票据号
     * cantonid 行政区划id
     * unitid  执行单位唯一标识
     *
     * @auther dinggaofei
     * @Date 2022/12/16 10:02
     * @description 验证手工缴款书是否可用，记录手工缴款书验证信息，并向财政发送信息，按报文规范（详见银行接口2.1）
     * 自动组织报文，将业务数据进行加密发送给财政；并将等待财政的回执信息，对回执信息进行解密分析，按财政回复的缴款书状态
     * 更新记录表，并将票据是否可用返回给调用者。
     */
    public BaseResult setChargeBillIsActive(ChargeBillVO chargeBillVO) {
        //xml解析器
        Serializer serializer = new Persister();
        //xml转换器
        StringWriter sw = new StringWriter();

        try {
            ChargeBillVO chargeBillAction = chargeBillMapper.findChargeBill(chargeBillVO.getBillnum());//.findChargeBillActionstate(chargeBillVO.getBillnum(), chargeBillVO.getBilltypeid(), 82);
            // 已缴费的直接返回
            if (chargeBillAction != null && (chargeBillAction.getBillstate() == 3 || chargeBillAction.getIsbankaffirm() ==1)) {
                chargeBillAction.setBillstate(3);
                serializer.write(chargeBillVO.gainChargeBillIsActive(), sw);
                return new BaseResult(sw.toString());
            }

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            chargeBillVO.setBilltypeid(1);
            chargeBillVO.setKeyword(82);
            chargeBillVO.setMessageid(messageid);
            if (chargeBillAction != null) {
                chargeBillMapper.updateChargeBill(chargeBillVO);
            } else {
                chargeBillVO.setBillid(sequenceService.getNextSeq("FSCHARGEBILLDETAILSEQ"));
                chargeBillMapper.saveChargeBill(chargeBillVO);
            }

            //获取缴款书对象
            SetChargeBillIsActive setChargeBillIsActive = chargeBillVO.gainSetChargeBillIsActive();
            //发送到财政
            boolean suc = messageService.sendAndRecvMessage("SETCHARGEBILLISACTIVE", messageid, setChargeBillIsActive, "2.0");
            if (suc) {
                //获取缴款书
                ChargeBillIsActive chargeBillIsActive = chargeBillMapper.findChargeBillActionstate(chargeBillVO.getBillnum(), chargeBillVO.getBilltypeid(), chargeBillVO.getKeyword()).gainChargeBillIsActive();
                serializer.write(chargeBillIsActive, sw);
                return new BaseResult(sw.toString());
            }
            return new BaseResult(ErrorCodeEnum.BILL_GET_TIMEOUT);

        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }

    /**
     * @param message 消息
     * @auther dinggaofei
     * @Date 2022/12/16 11:30
     * @description 记录手工缴款书票面和收款信息，并向财政发送信息，按报文规范（详见银行接口2.1）自动组织报文，将业务数据进行加密发送给财政；并将等待财政的
     * 回执信息，对回执信息进行解密分析，更新记录为已收款，并将回执处理结果返回给调用者。
     */
    public BaseResult setChargeBillManual(String message, String paychnl) {

        //xml解析器h
        Serializer serializer = new Persister();
        try {
            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            //获取缴款书对象
            SetChargeBillManual chargebill = serializer.read(SetChargeBillManual.class, new StringReader(message));

            //添加数据验证
            String retMsg = "";
            BigDecimal totalfunds = BigDecimal.ZERO;
            if (chargebill.getBillnum() == null || "".equals(chargebill.getBillnum().trim())) {
                retMsg += "票号未填写；";
            } else if (chargebill.getIswaitaffirm() == null) {
                retMsg += "待查确认标志错误；";
            } else if (chargebill.getPaybankdt() == null || "".equals(chargebill.getPaybankdt().trim())) {
                retMsg += "缴费时间未填写；";
            } else if (chargebill.getBankaffirm() == null || "".equals(chargebill.getBankaffirm().trim())) {
                retMsg += "交易流水号未填写；";
            } else if (chargebill.getBankstation() == null || "".equals(chargebill.getBankstation().trim())) {
                retMsg += "办理网点未填写；";
            } else if (chargebill.getPaywayid() == null || "".equals(chargebill.getPaywayid().trim())) {
                retMsg += "付款方式未填写；";
            } else if (chargebill.getCantonid() == null || "".equals(chargebill.getCantonid().trim())) {
                retMsg += "行政区划未填写；";
            } else if (chargebill.getUnitid() == null || "".equals(chargebill.getUnitid().trim())) {
                retMsg += "收款单位未填写；";
            } else if (chargebill.getPayer() == null || "".equals(chargebill.getPayer().trim())) {
                retMsg += "付款人未填写；";
            } else if (chargebill.getFilldate() == null || "".equals(chargebill.getFilldate().trim())) {
                retMsg += "开票日期未填写；";
            } else if (chargebill.getBankid() == null || "".equals(chargebill.getBankid().trim())) {
                retMsg += "收款账户未填写；";
            } else if (chargebill.getOriginfund() == null || "".equals(chargebill.getOriginfund().trim())) {
                retMsg += "缴款金额未填写；";
            } else if (chargebill.getPayee() == null || "".equals(chargebill.getPayee().trim())) {
                retMsg += "收款账户名称未填写；";
            } else if (chargebill.getPayeebank() == null || "".equals(chargebill.getPayeebank().trim())) {
                retMsg += "收款方银行未填写；";
            } else if (chargebill.getIshand() == null || !"1".equals(chargebill.getIshand().trim())) {
                retMsg += "手工票标识未设定";
            } else if (chargebill.getChargebilldetail() == null || chargebill.getChargebilldetail().size() == 0) {
                retMsg += "缴款项目未填写；";
            } else if (chargebill.getChargebilldetail().size() > 0) {
                for (int i = 0; i < chargebill.getChargebilldetail().size(); i++) {
                    SetChargeBillManualDetailDTO detail = chargebill.getChargebilldetail().get(i);
                    if (detail.getFromitemid() == null || "".equals(detail.getFromitemid().trim())) {
                        retMsg += "缴款项目未填写；";
                        break;
                    } else if (detail.getItemcode() == null || "".equals(detail.getItemcode().trim())) {
                        retMsg += "缴款项目未填写；";
                        break;
                    } else if (detail.getItemname() == null || "".equals(detail.getItemname().trim())) {
                        retMsg += "缴款项目未填写；";
                        break;
                    } else if (!(detail.getOriginfund()).equals(detail.getCurrentfund())) {
                        retMsg += "缴款项目未填写；";
                        break;
                    } else {
                        BigDecimal fund = new BigDecimal(detail.getCurrentfund());
                        fund = fund.setScale(2, BigDecimal.ROUND_HALF_UP);
                        totalfunds = totalfunds.add(fund);
                    }
                }
            }
            BigDecimal originfund = new BigDecimal(chargebill.getOriginfund());
            originfund = originfund.setScale(2, BigDecimal.ROUND_HALF_UP);
            if (totalfunds.compareTo(originfund) != 0) {
                retMsg += "缴款金额与明细项目不符；";
            }
            if (!"".equals(retMsg)) {
                logger.info("缴费参数错误。" + retMsg);
                return new BaseResult("3000", retMsg);
            }

            ChargeBillVO chaBillVO = chargeBillMapper.findChargeBill(chargebill.getBillnum());
            if (chaBillVO == null) {
                logger.info("电子缴款号不存在（票号：" + chargebill.getBillnum() + "）");
                return new BaseResult(ErrorCodeEnum.BILL_NOT_FOUND);
            }
            // 判断是否已缴费
            if (chaBillVO.getIsbankaffirm() == 1) {
                // 日期一致的允许二次提交
                if (!chargebill.getPaybankdt().substring(0, 10).equals(chaBillVO.getPaybankdt().substring(0, 10)))
                    return new BaseResult(ErrorCodeEnum.BILL_PAYED);
            } else if (chaBillVO.getBillstate() == 3) {
                return new BaseResult(ErrorCodeEnum.BILL_PAYED);
            }
            {
                if (chargebill.getPaywayid().length() == 1) {
                    chargebill.setPaywayid("0" + chargebill.getPaywayid());
                }
                chargebill.setPaywayid(Integer.toString(chargeBillMapper.findPayWay(chargebill.getPaywayid())));

                long billid = 0;
                //根据 唯一标示号和行政区划 查询银行信息是否存在
                if (bankMapper.selectBankCount(Long.valueOf(chargebill.getBankid()), chargebill.getCantonid()) > 0) {
                    /*
                     * 根据票号查询出最大的id  修改缴款书信息 并删除缴款书的详细信息,
                     */
                    billid = chargeBillMapper.selectChargeBillMax(chargebill.getBillnum());
                    ChargeBillVO chargeBillVO = new ChargeBillVO(chargebill);
                    chargeBillVO.setIssend(0);
                    chargeBillVO.setBillstate(1);
                    chargeBillVO.setIshand(1);
                    chargeBillVO.setIsbankaffirm(1);
                    chargeBillVO.setMessageid(messageid);
                    chargeBillVO.setBillid(Long.valueOf(billid));

                    if (chargeBillMapper.updateChargeBillId(chargeBillVO) < 1) {
                        return new BaseResult(ErrorCodeEnum.DB_ERR.getCode(), "更新一般缴款书手工票失败（" + chargebill.getBillnum() + "）");
                    }

                    //如果字段值为待查，将待查状态改为已用状态
                    if ("1".equals(chargebill.getIswaitaffirm())) {
                        WaitaffirmVO waitaffirmVO = new WaitaffirmVO();
                        waitaffirmVO.setBankaffirm(chargebill.getBankaffirm());
                        waitaffirmVO.setBankid(chargeBillVO.getBankid());
                        waitaffirmVO.setBillstate(3);
                        waitaffirmVO.setPaybankdt(chargebill.getPaybankdt().substring(0, 10));
                        waitaffirmMapper.updateBankAffirm(waitaffirmVO);
                    }

                    OnlineOrder oo = new OnlineOrder();
                    oo.setBillnum(chargebill.getBillnum());
                    oo.setAmt(chargebill.getOriginfund());
                    oo.setBankaffirm(chargebill.getBankaffirm());
                    oo.setBilltype(5);
                    oo.setPaybankdt(chargebill.getPaybankdt());
                    oo.setPaychnl(paychnl);
                    oo.setPayee(chargebill.getPayee());
                    oo.setPayeeaccount(chargebill.getPayeeaccount());
                    oo.setPayer(chargebill.getPayer());
                    oo.setPayeraccount(chargebill.getPayeraccount());
                    oo.setPaytype(1);
                    onlineOrderService.saveOnlineOrder(oo);

                    chargeBillMapper.deleteChargebilldetail(chargeBillVO.getBillid());
                    List<ChargeBillDetailVO> detail = new ArrayList<>();

                    /*
                     * 遍历出想要的类型，批量插入 缴款书详细信息表
                     */
                    ArrayList<SetChargeBillManualDetailDTO> chargebilldetail = chargebill.getChargebilldetail();
                    if (chargebilldetail.size() > 0) {
                        for (SetChargeBillManualDetailDTO setChargeBillManualDetailDTO : chargebilldetail) {
                            ChargeBillDetailVO chargeBillDetailVO = new ChargeBillDetailVO(setChargeBillManualDetailDTO);
                            chargeBillDetailVO.setBillheadid(billid);
                            chargeBillDetailVO.setDetailid(sequenceService.getNextSeq("FSCHARGEBILLDETAILSEQ"));
                            detail.add(chargeBillDetailVO);
                        }
                    }
                    if (detail.size() > 0) {
                        chargeBillMapper.saveChargeBillManualDetail(detail);
                    }
                }

                //发送到财政
                messageService.sendMessage("SETCHARGEBILLMANUAL", messageid, chargebill, "2.0");
                // 写凭证
                pzkService.savePzmsg("SETCHARGEBILLMANUALPZK", chargebill);
                return new BaseResult();
            }

        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e.toString());
            return new BaseResult("3100", "缴费异常" + e.getMessage());
        }
    }

    /**
     * 财政返回票据，入库，一般缴款书
     * @param data 财政报文
     * @param billstate 票据状态
     * @param sn 消息sn
     */
    public void setChargeBill(String data, int billstate, String sn) {
        try {
            //缴款书正常
            if (billstate == 1) {
                //xml解析器
                Serializer serializer = new Persister();
                //返回缴款书对象
                SetChargeBill setChargeBill = serializer.read(SetChargeBill.class, new StringReader(data));
                saveSetChargeBill(new ChargeBillVO(setChargeBill));
            } else if (billstate > 1){
                long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
                chargeBillMapper.updateChargeBillIsActivestate(messageid, billstate);
            }
        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e.toString(), e);
        }
    }

    private void saveSetChargeBill(ChargeBillVO chargebill) throws Exception {
        chargebill.setIssend(2);
        chargebill.setBillstate(1);
        chargebill.setIshand(0);
        if (chargeBillMapper.updateChargeBillNum(chargebill) < 1) return;

        long billid = chargeBillMapper.selectChargeBillMax(chargebill.getBillnum());
        chargebill.setBillid(billid);

        chargeBillMapper.deleteChargebilldetail(billid);

        ArrayList<SetChargeBillDetailDTO> chargebilldetail = chargebill.getChargebilldetail();
        ArrayList<ChargeBillDetailVO> chargeBillDetailVOS = new ArrayList<>();
        for (SetChargeBillDetailDTO setChargeBillDetailDTO : chargebilldetail) {
            ChargeBillDetailVO chargeBillDetailVO = new ChargeBillDetailVO(setChargeBillDetailDTO);
            chargeBillDetailVO.setBillheadid(billid);
            chargeBillDetailVO.setDetailid(sequenceService.getNextSeq("FSCHARGEBILLDETAILSEQ"));
            chargeBillDetailVOS.add(chargeBillDetailVO);
        }
        chargeBillMapper.saveChargeBillManualDetailPart(chargeBillDetailVOS);
    }

    /**
     * 手工票验证，财政返回
     * @param billstate 状态
     * @param sn 消息sn
     * @return
     */
    public int updateChargeBillIsActivestate(int billstate, String sn) {
        long messageid = Long.parseLong(sn.substring(sn.indexOf("-") + 1));
        return chargeBillMapper.updateChargeBillIsActivestate(messageid, billstate);

    }

    /** 发送财政，web */
    public BaseResult sendChargebill(String billids) {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<ChargeBillVO> chargeBillList = chargeBillMapper.findChargeBillList(ids);
        for (ChargeBillVO vo : chargeBillList) {
            sendChargebill(vo);
        }

        return new BaseResult();
    }

    // 发送财政，票号
    public BaseResult sendChargebill(ChargeBillVO vo) {
        if (vo.getIsbankaffirm() == 0) return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), "不允许发送未缴费单据");

        // 发送财政
        try {
            if (vo.getIshand() == 1) {
                // 手工票
                SetChargeBillManual chargeBill = new SetChargeBillManual();
                chargeBill.setKeyword(StringUtil.toStr(vo.getKeyword()));
                chargeBill.setBillnum(vo.getBillnum());
                chargeBill.setEticketnum(vo.getEticketnum());
                chargeBill.setCantonid(StringUtil.toStr(vo.getCantonid()));
                chargeBill.setUnitid(StringUtil.toStr(vo.getUnitid()));
                chargeBill.setHallid(StringUtil.toStr(vo.getHallid()));
                chargeBill.setFilldate(vo.getFilldate());
                chargeBill.setPayer(vo.getPayer());
                chargeBill.setPayeraccount(vo.getPayeraccount());
                chargeBill.setPayerbank(vo.getPayerbank());
                chargeBill.setBankid(StringUtil.toStr(vo.getBankid()));
                chargeBill.setPayee(vo.getPayee());
                chargeBill.setPayeeaccount(vo.getPayeeaccount());
                chargeBill.setPayeebank(vo.getPayeebank());
                chargeBill.setMemo(vo.getMemo());
                chargeBill.setVertifycode(vo.getVertifycode());
                chargeBill.setOriginfund(vo.getOriginfund().toPlainString());
                chargeBill.setIsscale(StringUtil.toStr(vo.getIsscale()));
                chargeBill.setIshand("1");
                chargeBill.setPaybankdt(vo.getPaybankdt());
                chargeBill.setBankaffirm(vo.getBankaffirm());
                chargeBill.setBankstation(vo.getBankstation());
                chargeBill.setIswaitaffirm(StringUtil.toStr(vo.getIncomeway()));
                chargeBill.setWritedate(vo.getWritedate());
                chargeBill.setWritename(vo.getWritename());
                chargeBill.setPaywayid(StringUtil.toStr(vo.getPayway()));
                long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
                //发送到财政
                messageService.sendMessage("SETCHARGEBILLMANUAL", messageid, chargeBill, "2.0");
            } else {
                long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
                //发送到财政
                messageService.sendMessage("SETCHARGEBILLDEPOSIT", messageid, vo.gainSetChargeBillDeposit(), "2.0");
            }
            return new BaseResult();
        } catch (Exception e) {
            logger.info("发送财政失败。" + e.toString(), e);
            return new BaseResult(ErrorCodeEnum.TLQ_ERR);
        }
    }

    /** 冲销 */
    public BaseResult cleanChargebill(String billids, String usercode) throws Exception {
        long[] ids = CommonUtil.getIdsLong(billids);
        if (ids.length == 0) return new BaseResult(ErrorCodeEnum.PARAM_ERR);
        List<ChargeBillVO> chargeBillList = chargeBillMapper.findChargeBillList(ids);

        Calendar cal = Calendar.getInstance();
        String cxTime = sdf.format(cal.getTime());
        cal.add(Calendar.MINUTE, 0 - nonTaxConfig.CxTime);
        String chkTime = sdf.format(cal.getTime());

        String errinfo = "";
        for (ChargeBillVO vo : chargeBillList) {
            if (StringUtil.isEmpty(vo.getSendtime()) || chkTime.compareTo(vo.getSendtime()) < 0) {
                setChargeBillBackOut(cxTime, usercode, vo);
                chargeBillMapper.backOutChargeBill(vo.getBillnum());
            } else {
                errinfo += vo.getBillnum() + ",";
            }
        }
        if (!errinfo.equals("")) {
            errinfo += "超时冲销失败,其他单据冲销成功!";
            return new BaseResult(ErrorCodeEnum.CUSTOM_ERR.getCode(), errinfo);
        } else {
            return new BaseResult();
        }
    }

    private BaseResult setChargeBillBackOut(String backoutdt, String backoutname, ChargeBillVO chargebill) {
        try {
            SetChargeBillBackOut out = new SetChargeBillBackOut();
            out.setBankid(StringUtil.toStr(chargebill.getBankid()));
            out.setBillid("0");
            out.setBillnum(chargebill.getBillnum());
            out.setEticketnum(chargebill.getEticketnum());
            out.setPayer(chargebill.getPayer());
            out.setFilldate(chargebill.getFilldate());
            out.setIswaitaffirm(StringUtil.toStr(chargebill.getIncomeway()));
            out.setOriginfund(chargebill.getOriginfund().toPlainString());
            out.setBackoutdt(backoutdt);
            out.setBackoutname(backoutname);
            out.setBankaffirm(chargebill.getBankaffirm());
            out.setBankstation(chargebill.getBankstation());
            out.setRemark("冲销");

            long messageid = sequenceService.getNextSeq("ELEMESSAGESEQ");
            //发送到财政
            messageService.sendMessage("SETCHARGEBILLBACKOUT", messageid, out, "2.0");
            // 写凭证
            pzkService.savePzmsgOut(BillStateUtil.BillType_ChargeBill, chargebill.getBillnum(), chargebill.getBankaffirm());

            return new BaseResult();
        } catch (Exception e) {
            logger.info("处理获取缴款书失败：" + e, e);
            return new BaseResult(ErrorCodeEnum.UNKNOWN_ERR);
        }
    }

    /**
     * 缴款书列表导出
     *
     * @return
     */
    public void listChargeBillExport(long bankid, String paybankdt, HttpServletResponse response) throws IOException {
        if (bankid == 0 || StringUtil.isEmpty(paybankdt)) return;

        ChargeBillVO vo = new ChargeBillVO();
        vo.setBankid(bankid);
        vo.setPaybankdt(paybankdt);
        List<ChargeBillVO> list = chargeBillMapper.selectChargeBillPage(vo);
        String[] headers = {"流水号", "票据号", "电子缴款书", "行政区划", "区划编码", "区划名称", "执收单位唯一标识号", "单位（部门）编码", "单位（部门）名称", "缴款人", "缴款人账号", "缴款人开户行", "收款账户id", "收款户名", "收款银行账号", "收款银行开户行", "票面总金额", "银行收款时间", "银行网点", "银行交易流水号", "缴款方式", "票据类型", "传输状态", "_status", "发送时间", "填写时间", "是否是待查确认", "经办人", "经办日期"};
        //数据键名或者MODEL类字段名
        String[] col = {"billid", "billnum", "eticketnum", "cantonid", "cantoncode", "cantonname", "unitid", "unitcode", "unitname", "payer", "payeraccount", "payerbank", "bankid", "payee", "payeeaccount", "payeebank", "originfund", "paybankdt", "bankstation", "bankaffirm", "payway", "ishand", "issend", "billstate", "sendtime", "writedate", "incomeway", "writename", "writedate"};
        ExportSXSSFUtil ex = new ExportSXSSFUtil();
        SXSSFWorkbook workbook = ex.exportExcelSXSSF("缴款书列表", headers, col, list, null);
        response.setContentType("application/vnd.ms-excel");
        response.setHeader("Content-Disposition", "attachment;filename=" + new String(("缴款书列表.xls").getBytes(), "iso-8859-1"));
        OutputStream ouputStream = response.getOutputStream();
        workbook.write(ouputStream);
        ouputStream.flush();
        ouputStream.close();

    }

    public BaseResult chargebillhandpayview(String billnum, Map data, UserVO user) {
        try {
            CommBankService cbs = new CommBankService();
            String bankaffirm = cbs.createBankAffirm("sbp");
            if (data.get("bankaffirm") != null && !data.get("bankaffirm").toString().trim().equals("")) {
                bankaffirm = data.get("bankaffirm").toString().trim();
            }
            BankStationVO bankStationVO = baseDataMapper.getBankStation(user.getBankStationId());

            String list_xml = createListXml(data);
            System.out.println("list_xml=" + list_xml);
            StringBuffer buf = new StringBuffer();
            buf.append("<bill>");
            buf.append("<keyword>82</keyword>");
            buf.append("<billnum>");
            buf.append(data.get("billnum") != null ? data.get("billnum").toString() : "");
            buf.append("</billnum>");
            buf.append("<eticketnum></eticketnum>");
            buf.append("<cantonid>");
            buf.append(data.get("cantonid") != null ? data.get("cantonid").toString() : "");
            buf.append("</cantonid>");
            buf.append("<unitid>");
            buf.append(data.get("unitid") != null ? data.get("unitid").toString() : "");
            buf.append("</unitid>");
            buf.append("<hallid></hallid>");
            buf.append("<filldate>");
            buf.append(data.get("filldate") != null ? data.get("filldate").toString() : "");
            buf.append("</filldate>");
            buf.append("<payer>");
            buf.append(data.get("payer") != null ? data.get("payer").toString() : "");
            buf.append("</payer>");
            buf.append("<payeraccount>");
            buf.append(data.get("payeraccount") != null ? data.get("payeraccount").toString() : "");
            buf.append("</payeraccount>");
            buf.append("<payerbank>");
            buf.append(data.get("payerbank") != null ? data.get("payerbank").toString() : "");
            buf.append("</payerbank>");
            buf.append("<bankid>");
            buf.append(data.get("bankid") != null ? data.get("bankidone").toString() : "");
            buf.append("</bankid>");
            buf.append("<payee>");
            buf.append(data.get("payee") != null ? data.get("payee").toString() : "");
            buf.append("</payee>");
            buf.append("<payeeaccount>");
            buf.append(data.get("payeeaccount") != null ? data.get("payeeaccount").toString() : "");
            buf.append("</payeeaccount>");
            buf.append("<payeebank>");
            buf.append(data.get("payeebank") != null ? data.get("payeebank").toString() : "");
            buf.append("</payeebank>");
            buf.append("<memo></memo>");
            buf.append("<vertifycode></vertifycode>");
            buf.append("<originfund>");
            buf.append(data.get("originfund") != null ? data.get("originfund").toString() : "");
            buf.append("</originfund>");
            buf.append("<isscale>0</isscale>");
            buf.append("<ishand>1</ishand>");
            buf.append("<paybankdt>");
            buf.append(GTimeUtil.getDateTimeMark());
            buf.append("</paybankdt>");
            buf.append("<bankaffirm>");
            buf.append(bankaffirm);
            buf.append("</bankaffirm>");
            buf.append("<bankstation>" + bankStationVO.getBankstationcode() + "</bankstation>");
            buf.append("<paywayid>");
            buf.append(data.get("paywaycode") != null ? data.get("paywaycode").toString() : "");
            buf.append("</paywayid>");
            buf.append("<iswaitaffirm>0</iswaitaffirm>");
            buf.append("<writename>");
            buf.append(user.getUserName());
            buf.append("</writename>");
            buf.append("<writedate>");
            buf.append(GTimeUtil.getDateMark());
            buf.append("</writedate>");
            buf.append("<details>");
            buf.append(list_xml);
            buf.append("</details>");
            buf.append("</bill>");
            String xml = buf.toString();
            System.out.println("create xml=" + xml);

            //setChargeBillManual(xml, true);
            BaseResult baseResult = setChargeBillManual(xml, "");
            return baseResult;
        } catch (Exception e) {
            e.printStackTrace();
            return new BaseResult("3101", "缴费异常");
        }
    }

    public String createListXml(Map data) {
        if (data.get("itemcode1") != null && data.get("upperlimit1") != null) {
            String[] upperlimit1s = data.get("upperlimit1").toString().split("~~");
            data.put("upperlimit1", upperlimit1s[0]);
            data.put("lowerlimit1", upperlimit1s[1]);
        }
        if (data.get("itemcode2") != null && data.get("upperlimit2") != null) {
            String[] upperlimit2s = data.get("upperlimit2").toString().split("~~");
            data.put("upperlimit2", upperlimit2s[0]);
            data.put("lowerlimit2", upperlimit2s[1]);
        }
        if (data.get("itemcode3") != null && data.get("upperlimit3") != null) {
            String[] upperlimit3s = data.get("upperlimit3").toString().split("~~");
            data.put("upperlimit3", upperlimit3s[0]);
            data.put("lowerlimit3", upperlimit3s[1]);
        }

        StringBuffer buf = new StringBuffer();
        for (int i = 1; i <= 3; i++) {
            if (data.get("ishave" + i) != null && data.get("ishave" + i).toString().equals("true")) {
                buf.append("<detail>");
                buf.append("<detailid>0</detailid>");
                buf.append("<fromitemid>");
                buf.append(data.get("fromitemid" + i) != null ? data.get("fromitemid" + i).toString() : "");
                buf.append("</fromitemid>");
                buf.append("<itemstandtype>");
                buf.append(data.get("lowerlimit" + i) != null ? data.get("lowerlimit" + i).toString() : "");
                buf.append("～～");
                buf.append(data.get("upperlimit" + i) != null ? data.get("upperlimit" + i).toString() : "");
                buf.append("</itemstandtype>");
                buf.append("<itemcode>");
                buf.append(data.get("itemcode" + i) != null ? data.get("itemcode" + i).toString() : "");
                buf.append("</itemcode>");
                buf.append("<itemname>");
                buf.append(data.get("itemname" + i) != null ? data.get("itemname" + i).toString() : "");
                buf.append("</itemname>");
                buf.append("<measureunit></measureunit>");
                buf.append("<originfund>");
                buf.append(data.get("originfund" + i) != null ? data.get("originfund" + i).toString() : "");
                buf.append("</originfund>");
                buf.append("<currentfund>");
                buf.append(data.get("originfund" + i) != null ? data.get("originfund" + i).toString() : "");
                buf.append("</currentfund>");
                buf.append("<provincescale>0.00</provincescale>");
                buf.append("<cityscale>0.00</cityscale>");
                buf.append("<amount>");
                buf.append(data.get("sl" + i) != null ? data.get("sl" + i).toString() : "");
                buf.append("</amount>");
                buf.append("</detail>");
            }
        }
        return buf.toString();
    }

}
